function [xPatch, yPatch, real_ysize] = parsePatchSize(Patch)
% Patch.xflow = 'Bicubic->I->FSRCNN_BATCH';
% Patch.xflow = 'Bicubic->Bicubic->VDSR0';

xPatch = setPatch('x', Patch);
yPatch = setPatch('y', Patch);

%%
xFlowList = strsplit(Patch.xflow, '->');
yFlowList = strsplit(Patch.yflow, '->');
if length(xFlowList) < 2
    error('Patch.xflow should have >= 2 components at least!');
end

%%
xsize = yPatch.size / Patch.scale;
xsize = estimateSize(xsize, Patch.scale, xFlowList(2 : end), true);
real_ysize = estimateSize(xsize, Patch.scale, yFlowList, false);

function xsize = estimateSize(xsize, scale, FlowList, bLeft)
for i = 1 : length(FlowList)
    if ~strcmp(FlowList{i}, 'I')
        break
    end
    % hDeploy = srmodel.getDeployFunc(strtrim(flowList{i}), Patch.scale);
    % x = hDeploy(x);
end

if i == length(FlowList)
    return
end

if bLeft
    xsize = scale * xsize;
    return
end

bUpscale = false;
for i = i+1 : length(FlowList)
    if strcmp(FlowList{i}, 'FSRCNN')
        % xsize = Patch.scale * xsize - Patch.scale + 1;
        xsize = FSRCNN.getOutputSize(xsize);
        continue
    end
    if ~bUpscale
        bUpscale = true;
        xsize = scale * xsize;
    end
end


function patch = setPatch(xyend, Patch)
switch xyend
    case 'x'
        patch.flow = Patch.xflow;
        patch.scale = Patch.scale;
    case 'y'
        patch.flow = Patch.yflow;
        Patch.ysize = unique(Patch.ysize, 'stable');
        patch.size = ceil(Patch.ysize / Patch.scale) * Patch.scale;
        patch.stride = patch.size - Patch.overlap;
end
patch.flow = regexprep(patch.flow, '\s*', '');

% if Patch.stride > Patch.size
%     warning('Patch.stride might be too big, and it has been clipped to Patch.size-1');
% end

%%
% function yPatch = get_ypatch_crop(xPatch, yPatch, FlowList)
% if ~strcmp(FlowList{2}, 'I')
%     yPatch.crop = @(x) x;
%     return
% end
% 
% x_p = floor((xsize - 1)/2);
% y_p = floor((yPatch.size + Patch.scale)/2 - 1);
% r_y = Patch.scale * (1 + x_p) - y_p;
% yPatch.crop = @(x) x(r_y : end, r_y : end);

% function ysize = estimate_osize(xsize, scale, FlowList)
% x = rand(xsize);
% for i = 3 : length(FlowList)
%     hDeploy = srmodel.getDeployFunc(strtrim(FlowList{i}), scale);
%     x = hDeploy(x);
% end
% ysize = size(x, 1);

% function [yPatch, hImgProcess] = parsePatch(xPatch)
% % Ref: Accelerating the Super-Resolution Convolutional Neural Network
% % As we train our models with the Caffe package, 
% %  its deconvolution filters will generate the output with size (n*size_input - n + 1)^2
% %  instead of (n*size_input)^2. So we also crop (n - 1)-pixel borders on the HR
% %  sub-images. Finally, for ��2, ��3 and ��4, we set the size of LR/HR sub-images
% %  to be 10^2/19^2, 7^2/19^2 and 6^2/21^2, respectively.
% 
% splitpattern = '->';
% UpsampList = strsplit(xPatch.upsamp, splitpattern);
% 
% yPatch.scale = xPatch.scale;
% if ~strcmp(UpsampList{1}, 'I')
%     yPatch.size = xsize;
%     yPatch.stride = xPatch.stride;
%     % yPatch.shift = [1 1];
%     hImgProcess = @(x) x;
% else
%     if length(UpsampList) > 1 % for cascade refinement
%         yPatch.size = xsize * xPatch.scale;
%     else % for training FSRCNN in Caffe
%         yPatch.size = xsize * xPatch.scale - (xPatch.scale - 1);
%     end
%     % yPatch.stride = xPatch.scale * xPatch.stride;
%     yPatch.stride = yPatch.size - 1;
%     
%     x_p = floor((xsize - 1)/2);
%     y_p = floor((yPatch.size + xPatch.scale)/2 - 1);
%     r_y = xPatch.scale * (1 + x_p) - y_p;
%     % c_y = Patch.scale * (1 + x_p) - y_p;
%     % yPatch.shift = [r_y r_y];
%     
%     hImgProcess = @(x) x(r_y : end, r_y : end);
% end
